1 2 3 4 5 6 7 8 9 10 11 12 public class StringAppendOperator extends MergeOperator { public StringAppendOperator () { super (newSharedStringAppendOperator()); } private native static long newSharedStringAppendOperator () ; @Override protected final native void disposeInternal (final long handle) ; }
以上代码是调用native方法的java代码.
在Java中native是关键字,它一般在本地声明,异地用C和C++来实现.
1 2 3 4 5 声明有以下几点注意: 1. native与访问控制符前后的关系不受限制. 2. 必须在返回类型之前 3. 它一般为非抽象类方法. 4. native方法在异地实现,像抽象方法一样,所以没有方法体,以分号结束.
下面是对应的C++实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 jlong Java_org_rocksdb_StringAppendOperator_newSharedStringAppendOperator ( JNIEnv* , jclass , jchar jdelim) { auto * sptr_string_append_op = new std::shared_ptr <ROCKSDB_NAMESPACE::MergeOperator>( ROCKSDB_NAMESPACE::MergeOperators::CreateStringAppendOperator ( (char )jdelim)); return reinterpret_cast <jlong>(sptr_string_append_op); } void Java_org_rocksdb_StringAppendOperator_disposeInternal (JNIEnv* , jobject , jlong jhandle) { auto * sptr_string_append_op = reinterpret_cast <std::shared_ptr<ROCKSDB_NAMESPACE::MergeOperator>*>( jhandle); delete sptr_string_append_op; }
问题:那这个对应关系是怎么找到的呢,就是说java的接口,怎么找到c++里的这个方法的呢?
include 引入
Signature: (Ljava/lang/String;)V 函数的标记符。当从本地方法端访问Java端的方法时,会用到这个标记符。JNI中为每种数据类型也定义了标记符,标记符的规则请查看JNI标准文档。
native方法的使用方式 1 2 3 1. 用loadLibrary导入存在源文件目录下的*.dll文件, 2. 然后定义native方法时,与c/c++实现的函数有相同的参数和返回类型. 3.方法被映射为固定的形式。其中函数名的映射规则是(Java_包名_类名_方法名)。
如下rocksDB中的使用方式. 见 org.rocksdb.NativeLibraryLoader
1 2 3 4 5 6 7 8 9 10 11 public synchronized void loadLibrary (final String tmpDir) throws IOException { try { System.loadLibrary(sharedLibraryName); } catch (final UnsatisfiedLinkError ule1) { try { System.loadLibrary(jniLibraryName); } catch (final UnsatisfiedLinkError ule2) { loadLibraryFromJar(tmpDir); } } }
那.ddl , .so文件又是什么,怎么来的呢?先说所JNI
JNI JNI是Java Native Interface的缩写,中文为JAVA本地调用.它允许Java代码和其它语言写的代码进行交互.
JNI使得运行在JVM虚拟机上的JAVA代码能够操作使用其它语言编写的应用程序和库,比如C/C++以及汇编语言等.
JNI的设计目的:
1 2 3 ·标准的java类库可能不支持你的程序所需的特性。 ·或许你已经有了一个用其他语言写成的库或程序,而你希望在java程序中使用它。 ·你可能需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的java程序中调用这些功能。
JAVA中native方法调用